home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 (Walnut Creek) / Aminet - June 1993 [Walnut Creek].iso / usenet / sources / volume2 / editors / stevie.3 < prev    next >
Text File  |  1988-12-02  |  59KB  |  2,343 lines

  1. Path: xanth!mcnc!gatech!bloom-beacon!mit-eddie!ll-xn!adelie!infinet!ulowell!page
  2. From: page@swan.ulowell.edu (Bob Page)
  3. Newsgroups: comp.sources.amiga
  4. Subject: v02i083:  stevie - vi editor clone, Part03/04
  5. Message-ID: <10421@swan.ulowell.edu>
  6. Date: 2 Dec 88 01:44:29 GMT
  7. Organization: University of Lowell, Computer Science Dept.
  8. Lines: 2332
  9. Approved: page@swan.ulowell.edu
  10.  
  11. Submitted-by: grwalter@watcgl.waterloo.edu
  12. Posting-number: Volume 2, Issue 83
  13. Archive-name: editors/stevie.3
  14.  
  15. #    This is a shell archive.
  16. #    Remove everything above and including the cut line.
  17. #    Then run the rest of the file through sh.
  18. #----cut here-----cut here-----cut here-----cut here----#
  19. #!/bin/sh
  20. # shar:    Shell Archiver
  21. #    Run the following text with /bin/sh to create:
  22. #    screen.c
  23. #    search.c
  24. #    source.doc
  25. #    stevie.doc
  26. #    stevie.h
  27. #    term.h
  28. #    updateNextscreen.c
  29. #    updateRealscreen.c
  30. # This archive created: Thu Dec  1 20:37:59 1988
  31. cat << \SHAR_EOF > screen.c
  32. /*
  33.  * STEVIE - Simply Try this Editor for VI Enthusiasts
  34.  *
  35.  * Code Contributions By : Tim Thompson           twitch!tjt
  36.  *                         Tony Andrews           onecom!wldrdg!tony 
  37.  *                         G. R. (Fred) Walter    watmath!watcgl!grwalter 
  38.  */
  39.  
  40. #include "stevie.h"
  41.  
  42. /*
  43.  * The following variable is set (in cursupdate) to the number of physical
  44.  * lines taken by the line the cursor is on. We use this to avoid extra calls
  45.  * to plines(). The optimized routines updateline() and redrawline()
  46.  * make sure that the size of the cursor line hasn't changed. If so, lines below
  47.  * the cursor will move up or down and we need to call the routines
  48.  * updateNextscreen() and updateRealscreen() to examine the entire screen. 
  49.  */
  50. static int      Cline_size;    /* size (in rows) of the cursor line */
  51. static int      Cline_row;    /* starting row of the cursor line */
  52.  
  53. /*
  54.  * updateline() - like updateNextscreen() but only for cursor line 
  55.  *
  56.  * This determines whether or not we need to call updateNextscreen() to examine the
  57.  * entire screen for changes. This occurs if the size of the cursor line
  58.  * (in rows) hasn't changed.
  59.  */
  60. void
  61. updateline()
  62. {
  63.     int             row, col;
  64.     register char  *screenp;
  65.     LPTR            memp;
  66.     register char  *nextrow;
  67.     char            extra[16];
  68.     int             nextra = 0;
  69.     char            c;
  70.     int             n;
  71.     bool_t          eof;
  72.  
  73.     MustRedrawLine = TRUE;
  74.  
  75. #ifndef AMIGA
  76.     if (MustRedrawScreen) {
  77.     msg("STEVIE internal error: updateline called");
  78.     sleep(5);
  79.     }
  80. #endif
  81.  
  82.     screenp = Nextscreen + (Cline_row * Columns);
  83.  
  84.     memp = *Curschar;
  85.     memp.index = 0;
  86.  
  87.     eof = FALSE;
  88.     col = 0;
  89.     row = Cline_row;
  90.  
  91.     while (!eof) {
  92.  
  93.     /* Get the next character to put on the screen. */
  94.  
  95.     /*
  96.      * The 'extra' array contains the extra stuff that is inserted to
  97.      * represent special characters (tabs, and other non-printable stuff.
  98.      * The order in the 'extra' array is reversed. 
  99.      */
  100.  
  101.     if (nextra > 0)
  102.         c = extra[--nextra];
  103.     else {
  104.         c = gchar(&memp);
  105.         if (inc(&memp) == -1)
  106.         eof = TRUE;
  107.         /*
  108.          * when getting a character from the file, we may have to turn it
  109.          * into something else on the way to putting it into
  110.          * 'Nextscreen'. 
  111.          */
  112.         if (c == TAB && !P(P_LS)) {
  113.         strcpy(extra, "        ");
  114.         /* tab amount depends on current column */
  115.         nextra = ((P(P_TS) - 1) - col % P(P_TS));
  116.         c = ' ';
  117.         } else if (c == NUL && P(P_LS)) {
  118.         extra[0] = NUL;
  119.         nextra = 1;
  120.         c = '$';
  121.         } else if (c != NUL && (n = chars[c].ch_size) > 1) {
  122.         char           *p;
  123.         nextra = 0;
  124.         p = chars[c].ch_str;
  125.         /* copy 'ch-str'ing into 'extra' in reverse */
  126.         while (n > 1)
  127.             extra[nextra++] = p[--n];
  128.         c = p[0];
  129.         }
  130.     }
  131.  
  132.     if (c == NUL) {
  133.         row++;
  134.         /* get pointer to start of next row */
  135.         nextrow = &Nextscreen[row * Columns];
  136.         /* blank out the rest of this row */
  137.         while (screenp != nextrow)
  138.         *screenp++ = ' ';
  139.         col = 0;
  140.         break;
  141.     }
  142.     if (col >= Columns) {
  143.         row++;
  144.         col = 0;
  145.     }
  146.     /* store the character in Nextscreen */
  147.     *screenp++ = c;
  148.     col++;
  149.     }
  150.     if ((row - Cline_row) == Cline_size)
  151.     updateNextscreen();
  152. }
  153.  
  154. /*
  155.  * redrawline 
  156.  *
  157.  * Like updateRealscreen() but only for the cursor line. 
  158.  */
  159. void
  160. redrawline()
  161. {
  162.     register char  *np = Nextscreen + (Cline_row * Columns);
  163.     register char  *rp = Realscreen + (Cline_row * Columns);
  164.     register char  *endline;
  165.     int             row, col;
  166.     int             gorow = -1, gocol = -1;
  167.  
  168.     if (RedrawingDisabled)
  169.     return;
  170.  
  171.     if (!MustRedrawLine && !MustRedrawScreen)
  172.     return;
  173.  
  174.     if (MustRedrawScreen) {
  175.     msg("STEVIE internal error: redrawline called");
  176.     sleep(5);
  177.     }
  178.     endline = np + (Cline_size * Columns);
  179.  
  180.     row = Cline_row;
  181.     col = 0;
  182.  
  183.     outstr(T_CI);        /* disable cursor */
  184.  
  185.     for (; np < endline; np++, rp++) {
  186.     /* If desired screen (contents of Nextscreen) does not */
  187.     /* match what's really there, put it there. */
  188.     if (*np != *rp) {
  189.         /* if we are positioned at the right place, */
  190.         /* we don't have to use windgoto(). */
  191.         if (gocol != col || gorow != row) {
  192.         /*
  193.          * If we're just off by one, don't send an entire esc. seq.
  194.          * (this happens a lot!) 
  195.          */
  196.         if (gorow == row && gocol + 1 == col) {
  197.             outchar(*(np - 1));
  198.             gocol++;
  199.         } else
  200.             windgoto(gorow = row, gocol = col);
  201.         }
  202.         outchar(*rp = *np);
  203.         gocol++;
  204.     }
  205.     if (++col >= Columns) {
  206.         col = 0;
  207.         row++;
  208.     }
  209.     }
  210.     outstr(T_CV);        /* enable cursor again */
  211.  
  212.     MustRedrawScreen = FALSE;
  213. }
  214.  
  215. void
  216. screenclear()
  217. {
  218.     char           *rp, *np;
  219.     char           *end;
  220.  
  221.     outstr(T_ED);        /* clear the display */
  222.  
  223.     rp = Realscreen;
  224.     end = Realscreen + Rows * Columns;
  225.     np = Nextscreen;
  226.  
  227.     /* blank out the stored screens */
  228.     while (rp != end)
  229.     *rp++ = *np++ = ' ';
  230. }
  231.  
  232. void
  233. cursupdate()
  234. {
  235.     LPTR           *p;
  236.     char            c;
  237.     int             incr, nlines;
  238.     int             i;
  239.     int             didincr;
  240.  
  241.     if (bufempty()) {        /* special case - file is empty */
  242.     *Topchar = *Filemem;
  243.     *Curschar = *Filemem;
  244.     } else if (LINEOF(Curschar) < LINEOF(Topchar)) {
  245.     nlines = cntllines(Curschar, Topchar);
  246.     /*
  247.      * if the cursor is above the top of the screen, put it at the top of
  248.      * the screen.. 
  249.      */
  250.     *Topchar = *Curschar;
  251.     Topchar->index = 0;
  252.     /*
  253.      * ... and, if we weren't very close to begin with, we scroll so that
  254.      * the line is close to the middle. 
  255.      */
  256.     if (nlines > Rows / 3) {
  257.         for (i = 0, p = Topchar; i < Rows / 3; i++, *Topchar = *p)
  258.         if ((p = prevline(p)) == NULL)
  259.             break;
  260.     } else
  261.         s_ins(0, nlines - 1);
  262.     updateNextscreen();
  263.     } else if (LINEOF(Curschar) >= LINEOF(Botchar)) {
  264.     nlines = cntllines(Botchar, Curschar);
  265.     /*
  266.      * If the cursor is off the bottom of the screen, put it at the top
  267.      * of the screen.. ... and back up 
  268.      */
  269.     if (nlines > Rows / 3) {
  270.         p = Curschar;
  271.         for (i = 0; i < (2 * Rows) / 3; i++)
  272.         if ((p = prevline(p)) == NULL)
  273.             break;
  274.         *Topchar = *p;
  275.     } else {
  276.         scrollup(nlines);
  277.     }
  278.     updateNextscreen();
  279.     }
  280.     Cursrow = Curscol = Cursvcol = 0;
  281.     for (p = Topchar; p->linep != Curschar->linep; p = nextline(p))
  282.     Cursrow += plines(p);
  283.  
  284.     Cline_row = Cursrow;
  285.     Cline_size = plines(p);
  286.  
  287.     for (i = 0; i <= Curschar->index; i++) {
  288.     c = Curschar->linep->s[i];
  289.     /* A tab gets expanded, depending on the current column */
  290.     if (c == TAB && !P(P_LS))
  291.         incr = P(P_TS) - (Curscol % P(P_TS));
  292.     else
  293.         incr = chars[c].ch_size;
  294.     Curscol += incr;
  295.     Cursvcol += incr;
  296.     if (Curscol >= Columns) {
  297.         Curscol -= Columns;
  298.         Cursrow++;
  299.         didincr = TRUE;
  300.     } else
  301.         didincr = FALSE;
  302.     }
  303.     if (didincr)
  304.     Cursrow--;
  305.  
  306.     if (c == TAB && State == NORMAL && !P(P_LS)) {
  307.     Curscol--;
  308.     Cursvcol--;
  309.     } else {
  310.     Curscol -= incr;
  311.     Cursvcol -= incr;
  312.     }
  313.     if (Curscol < 0)
  314.     Curscol += Columns;
  315.  
  316.     if (set_want_col) {
  317.     Curswant = Cursvcol;
  318.     set_want_col = FALSE;
  319.     }
  320. }
  321.  
  322. /*
  323.  * The rest of the routines in this file perform screen manipulations. The
  324.  * given operation is performed physically on the screen. The corresponding
  325.  * change is also made to the internal screen image. In this way, the editor
  326.  * anticipates the effect of editing changes on the appearance of the screen.
  327.  * That way, when we call screenupdate a complete redraw isn't usually
  328.  * necessary. Another advantage is that we can keep adding code to anticipate
  329.  * screen changes, and in the meantime, everything still works. 
  330.  */
  331.  
  332. /*
  333.  * s_ins(row, nlines) - insert 'nlines' lines at 'row' 
  334.  */
  335. void
  336. s_ins(row, nlines)
  337.     int             row;
  338.     int             nlines;
  339. {
  340.     char           *s, *d;    /* src & dest for block copy */
  341.     char           *e;        /* end point for copy */
  342.     int             i;
  343.  
  344.     if ((T_IL[0] == NUL) || RedrawingDisabled || nlines <= 0)
  345.     return;
  346.  
  347.     /*
  348.      * It "looks" better if we do all the inserts at once 
  349.      */
  350.     outstr(T_SC);        /* save position */
  351.  
  352.     if (T_IL_B[0] == NUL) {
  353.     for (i = 0; i < nlines; i++) {
  354.         windgoto(row, 0);
  355.         outstr(T_IL);
  356.     }
  357.     } else {
  358.     windgoto(row, 0);
  359.     outstr(T_IL);
  360.     if (nlines >= 10)
  361.         outchar((char) (nlines / 10 + '0'));
  362.     outchar((char) (nlines % 10 + '0'));
  363.     outstr(T_IL_B);
  364.     }
  365.  
  366.     windgoto(Rows - 1, 0);    /* delete any garbage that may have */
  367.     outstr(T_EL);        /* been shifted to the bottom line */
  368.  
  369.     outstr(T_RC);        /* restore the cursor position */
  370.  
  371.     /*
  372.      * Now do a block move to update the internal screen image 
  373.      */
  374.     d = Realscreen + (Columns * (Rows - 1)) - 1;
  375.     s = d - (Columns * nlines);
  376.     e = Realscreen + (Columns * row);
  377.  
  378.     while (s >= e)
  379.     *d-- = *s--;
  380.  
  381.     /*
  382.      * Clear the inserted lines 
  383.      */
  384.     s = Realscreen + (row * Columns);
  385.     e = s + (nlines * Columns);
  386.     while (s < e)
  387.     *s++ = ' ';
  388. }
  389.  
  390. /*
  391.  * s_del(row, nlines) - delete 'nlines' lines at 'row' 
  392.  */
  393. void
  394. s_del(row, nlines)
  395.     int             row;
  396.     int             nlines;
  397. {
  398.     char           *s, *d, *e;
  399.     int             i;
  400.  
  401.     if ((T_DL[0] == NUL) || RedrawingDisabled || nlines <= 0)
  402.     return;
  403.  
  404.     outstr(T_SC);        /* save position */
  405.  
  406.     windgoto(Rows - 1, 0);    /* delete any garbage that */
  407.     outstr(T_EL);        /* was on the status line */
  408.  
  409.     /* delete the lines */
  410.     if (T_DL_B[0] == NUL) {
  411.     for (i = 0; i < nlines; i++) {
  412.         windgoto(row, 0);
  413.         outstr(T_DL);    /* delete a line */
  414.     }
  415.     } else {
  416.     windgoto(row, 0);
  417.     outstr(T_DL);
  418.     if (nlines >= 10)
  419.         outchar((char) (nlines / 10 + '0'));
  420.     outchar((char) (nlines % 10 + '0'));
  421.     outstr(T_DL_B);
  422.     }
  423.  
  424.     outstr(T_RC);        /* restore position */
  425.  
  426.     /*
  427.      * do a block move to update the internal image 
  428.      */
  429.     d = Realscreen + (row * Columns);
  430.     s = d + (nlines * Columns);
  431.     e = Realscreen + ((Rows - 1) * Columns);
  432.  
  433.     while (s < e)
  434.     *d++ = *s++;
  435.  
  436.     while (d < e)        /* clear the lines at the bottom */
  437.     *d++ = ' ';
  438. }
  439. SHAR_EOF
  440. cat << \SHAR_EOF > search.c
  441. /*
  442.  * STEVIE - Simply Try this Editor for VI Enthusiasts
  443.  *
  444.  * Code Contributions By : Tim Thompson           twitch!tjt
  445.  *                         Tony Andrews           onecom!wldrdg!tony 
  446.  *                         G. R. (Fred) Walter    watmath!watcgl!grwalter 
  447.  */
  448.  
  449. #include "stevie.h"
  450.  
  451. #ifdef AMIGA
  452. #include "/regexp/regexp.h"
  453. #else
  454. #include <regexp.h>        /* Henry Spencer's regular expression
  455.                  * routines */
  456. #endif
  457.  
  458. #ifdef    MEGAMAX
  459. overlay "search"
  460. #endif
  461.  
  462. /*
  463.  * This file contains various searching-related routines. These fall into
  464.  * three groups: string searches (for /, ?, n, and N), character searches
  465.  * within a single line (for f, F, t, T, etc), and "other" kinds of searches
  466.  * like the '%' command, and 'word' searches. 
  467.  */
  468.  
  469. /*
  470.  * String searches 
  471.  *
  472.  * The actual searches are done using Henry Spencer's regular expression
  473.  * library. 
  474.  */
  475.  
  476. #define    BEGWORD    "([^a-zA-Z0-9_]|^)"    /* replaces "\<" in search strings */
  477. #define    ENDWORD    "([^a-zA-Z0-9_]|$)"    /* likewise replaces "\>" */
  478.  
  479. bool_t begword;            /* does the search include a 'begin word'
  480.                  * match */
  481.  
  482. /*
  483.  * mapstring(s) - map special backslash sequences 
  484.  */
  485. static char    *
  486. mapstring(s)
  487.     char           *s;
  488. {
  489.     static char     ns[MAX_COLUMNS + 1];
  490.     char           *p;
  491.  
  492.     begword = FALSE;
  493.  
  494.     for (p = ns; *s; s++) {
  495.     if (*s != '\\') {    /* not an escape */
  496.         *p++ = *s;
  497.         continue;
  498.     }
  499.     switch (*++s) {
  500.       case '/':
  501.         *p++ = '/';
  502.         break;
  503.  
  504.       case '<':
  505.         strcpy(p, BEGWORD);
  506.         p += strlen(BEGWORD);
  507.         begword = TRUE;
  508.         break;
  509.  
  510.       case '>':
  511.         strcpy(p, ENDWORD);
  512.         p += strlen(ENDWORD);
  513.         break;
  514.  
  515.       default:
  516.         *p++ = '\\';
  517.         *p++ = *s;
  518.         break;
  519.     }
  520.     }
  521.     *p++ = NUL;
  522.  
  523.     return ns;
  524. }
  525.  
  526. static LPTR    *
  527. bcksearch(str)
  528.     char           *str;
  529. {
  530.     static LPTR     infile;
  531.     LPTR           *p;
  532.     regexp         *prog;
  533.     char           *s;
  534.     int             i;
  535.     bool_t          want_start = (*str == '^');    /* looking for start of line? */
  536.     char           *match;
  537.  
  538.     /* make sure str isn't empty */
  539.     if (str == NULL || *str == NUL)
  540.     return NULL;
  541.  
  542.     if ((prog = regcomp(str)) == NULL) {
  543.     emsg("Invalid search string");
  544.     return NULL;
  545.     }
  546.     p = Curschar;
  547.     dec(p);
  548.  
  549.     if (begword)        /* so we don't get stuck on one match */
  550.     dec(p);
  551.  
  552.     i = (want_start) ? 0 : p->index;
  553.  
  554.     do {
  555.     s = p->linep->s;
  556.  
  557.     if (regexec(prog, s)) {    /* match somewhere on line */
  558.  
  559.         if (want_start) {    /* could only have been one */
  560.         infile.linep = p->linep;
  561.         infile.index = (int) (prog->startp[0] - s);
  562.         free((char *) prog);
  563.         return (&infile);
  564.         }
  565.         /*
  566.          * Now, if there are multiple matches on this line, we have to
  567.          * get the last one. Or the last one before the cursor, if we're
  568.          * on that line. 
  569.          */
  570.  
  571.         match = prog->startp[0];
  572.  
  573.         while (regexec(prog, prog->endp[0])) {
  574.         if ((i >= 0) && ((prog->startp[0] - s) > i))
  575.             break;
  576.         match = prog->startp[0];
  577.         }
  578.  
  579.         if ((i >= 0) && ((match - s) > i)) {
  580.         i = -1;
  581.         continue;
  582.         }
  583.         infile.linep = p->linep;
  584.         infile.index = (int) (match - s);
  585.         free((char *) prog);
  586.         return (&infile);
  587.     }
  588.     i = -1;
  589.  
  590.     } while ((p = prevline(p)) != NULL);
  591.  
  592.     /*
  593.      * If wrapscan isn't set, bag the search now 
  594.      */
  595.     if (!P(P_WS)) {
  596.     free((char *) prog);
  597.     return NULL;
  598.     }
  599.     /* search backward from the end of the file */
  600.     p = prevline(Fileend);
  601.     do {
  602.     s = p->linep->s;
  603.  
  604.     if (regexec(prog, s)) {    /* match somewhere on line */
  605.  
  606.         if (want_start) {    /* could only have been one */
  607.         infile.linep = p->linep;
  608.         infile.index = (int) (prog->startp[0] - s);
  609.         free((char *) prog);
  610.         return (&infile);
  611.         }
  612.         /*
  613.          * Now, if there are multiple matches on this line, we have to
  614.          * get the last one. 
  615.          */
  616.  
  617.         match = prog->startp[0];
  618.  
  619.         while (regexec(prog, prog->endp[0]))
  620.         match = prog->startp[0];
  621.  
  622.         infile.linep = p->linep;
  623.         infile.index = (int) (match - s);
  624.         free((char *) prog);
  625.         return (&infile);
  626.     }
  627.     if (p->linep == Curschar->linep)
  628.         break;
  629.  
  630.     } while ((p = prevline(p)) != NULL);
  631.  
  632.     free((char *) prog);
  633.     return NULL;
  634. }
  635.  
  636. static LPTR    *
  637. fwdsearch(str)
  638.     char           *str;
  639. {
  640.     static LPTR     infile;
  641.     LPTR           *p;
  642.     regexp         *prog;
  643.     bool_t          want_start = (*str == '^');    /* looking for start of line? */
  644.  
  645.     char           *s;
  646.     int             i;
  647.  
  648.     if ((prog = regcomp(str)) == NULL) {
  649.     emsg("Invalid search string");
  650.     return NULL;
  651.     }
  652.     p = Curschar;
  653.     i = Curschar->index + 1;
  654.     do {
  655.     s = p->linep->s + i;
  656.     i = 0;
  657.  
  658.     if (regexec(prog, s)) {    /* got a match */
  659.         /*
  660.          * If we wanted the start of a line and we aren't really there,
  661.          * then a match doesn't count. 
  662.          */
  663.         if (want_start && (s != p->linep->s))
  664.         continue;
  665.  
  666.         infile.linep = p->linep;
  667.         infile.index = (int) (prog->startp[0] - p->linep->s);
  668.         free((char *) prog);
  669.         return (&infile);
  670.     }
  671.     } while ((p = nextline(p)) != NULL);
  672.  
  673.     /*
  674.      * If wrapscan isn't set, then don't scan from the beginning of the file.
  675.      * Just return failure here. 
  676.      */
  677.     if (!P(P_WS)) {
  678.     free((char *) prog);
  679.     return NULL;
  680.     }
  681.     /* search from the beginning of the file to Curschar */
  682.     for (p = Filemem; p != NULL; p = nextline(p)) {
  683.     s = p->linep->s;
  684.  
  685.     if (regexec(prog, s)) {    /* got a match */
  686.         infile.linep = p->linep;
  687.         infile.index = (int) (prog->startp[0] - s);
  688.         free((char *) prog);
  689.         return (&infile);
  690.     }
  691.     if (p->linep == Curschar->linep)
  692.         break;
  693.     }
  694.  
  695.     free((char *) prog);
  696.     return (NULL);
  697. }
  698.  
  699. static char    *laststr = NULL;
  700. static int      lastsdir;
  701.  
  702. static LPTR    *
  703. ssearch(dir, str)
  704.     int             dir;    /* FORWARD or BACKWARD */
  705.     char           *str;
  706. {
  707.     LPTR           *pos;
  708.  
  709.     if (dir == BACKWARD)
  710.     pos = bcksearch(mapstring(str));
  711.     else
  712.     pos = fwdsearch(mapstring(str));
  713.  
  714.     /*
  715.      * This is kind of a kludge, but its needed to make 'beginning of word'
  716.      * searches land on the right place. 
  717.      */
  718.     if (begword) {
  719.     if (pos->index != 0)
  720.         pos->index += 1;
  721.     }
  722.     if (laststr != str) {
  723.     if (laststr != NULL)
  724.         free(laststr);
  725.     laststr = strsave(str);
  726.     }
  727.     lastsdir = dir;
  728.  
  729.     return pos;
  730. }
  731.  
  732. void
  733. dosearch(dir, str)
  734.     int             dir;
  735.     char           *str;
  736. {
  737.     LPTR           *p;
  738.  
  739.     if ((p = ssearch(dir, str)) == NULL)
  740.     msg("Pattern not found");
  741.     else {
  742.     LPTR            savep;
  743.  
  744.     cursupdate();
  745.     /* if we're backing up, we make sure the line we're on */
  746.     /* is on the screen. */
  747.     setpcmark();
  748.     *Curschar = savep = *p;
  749.     cursupdate();
  750.     }
  751. }
  752.  
  753. void
  754. searchagain(dir)
  755.     int             dir;
  756. {
  757.     if (laststr == NULL)
  758.     beep();
  759.     else
  760.     dosearch(dir, laststr);
  761.  
  762.     lastsdir = dir;
  763. }
  764.  
  765. #define    OTHERDIR(x)    (((x) == FORWARD) ? BACKWARD : FORWARD)
  766.  
  767. void
  768. repsearch(flag)
  769.     bool_t          flag;
  770. {
  771.     int             dir = lastsdir;
  772.  
  773.     if (laststr == NULL)
  774.     beep();
  775.     else
  776.     dosearch(flag ? OTHERDIR(lastsdir) : lastsdir, laststr);
  777.  
  778.     lastsdir = dir;
  779. }
  780.  
  781. /*
  782.  * regerror - called by regexp routines when errors are detected. 
  783.  */
  784. void
  785. regerror(s)
  786.     char           *s;
  787. {
  788.     emsg(s);
  789. }
  790.  
  791. /*
  792.  * Character Searches 
  793.  */
  794.  
  795. static char     lastc = NUL;    /* last character searched for */
  796. static int      lastcdir;    /* last direction of character search */
  797. static int      lastctype;    /* last type of search ("find" or "to") */
  798.  
  799. /*
  800.  * searchc(c, dir, type) 
  801.  *
  802.  * Search for character 'c', in direction 'dir'. If type is 0, move to the
  803.  * position of the character, otherwise move to just before the char. 
  804.  */
  805. bool_t
  806. searchc(c, dir, type)
  807.     char            c;
  808.     int             dir;
  809.     int             type;
  810. {
  811.     LPTR            save;
  812.  
  813.     save = *Curschar;        /* save position in case we fail */
  814.     lastc = c;
  815.     lastcdir = dir;
  816.     lastctype = type;
  817.  
  818.     /*
  819.      * On 'to' searches, skip one to start with so we can repeat searches in
  820.      * the same direction and have it work right. 
  821.      */
  822.     if (type)
  823.     (dir == FORWARD) ? oneright() : oneleft();
  824.  
  825.     while ((dir == FORWARD) ? oneright() : oneleft()) {
  826.     if (gchar(Curschar) == c) {
  827.         if (type)
  828.         (dir == FORWARD) ? oneleft() : oneright();
  829.         return TRUE;
  830.     }
  831.     }
  832.     *Curschar = save;
  833.     return FALSE;
  834. }
  835.  
  836. bool_t
  837. crepsearch(flag)
  838.     int             flag;
  839. {
  840.     int             dir = lastcdir;
  841.     int             rval;
  842.  
  843.     if (lastc == NUL)
  844.     return FALSE;
  845.  
  846.     rval = searchc(lastc, flag ? OTHERDIR(lastcdir) : lastcdir, lastctype);
  847.  
  848.     lastcdir = dir;        /* restore dir., since it may have changed */
  849.  
  850.     return rval;
  851. }
  852.  
  853. /*
  854.  * "Other" Searches 
  855.  */
  856.  
  857. /*
  858.  * showmatch - move the cursor to the matching paren or brace 
  859.  */
  860. LPTR           *
  861. showmatch()
  862. {
  863.     static LPTR     pos;
  864.     int             (*move) (), inc(), dec();
  865.     char            initc = gchar(Curschar);    /* initial char */
  866.     char            findc;    /* terminating char */
  867.     char            c;
  868.     int             count = 0;
  869.  
  870.     pos = *Curschar;        /* set starting point */
  871.  
  872.     switch (initc) {
  873.  
  874.       case '(':
  875.     findc = ')';
  876.     move = inc;
  877.     break;
  878.       case ')':
  879.     findc = '(';
  880.     move = dec;
  881.     break;
  882.       case '{':
  883.     findc = '}';
  884.     move = inc;
  885.     break;
  886.       case '}':
  887.     findc = '{';
  888.     move = dec;
  889.     break;
  890.       case '[':
  891.     findc = ']';
  892.     move = inc;
  893.     break;
  894.       case ']':
  895.     findc = '[';
  896.     move = dec;
  897.     break;
  898.       default:
  899.     return (LPTR *) NULL;
  900.     }
  901.  
  902.     while ((*move) (&pos) != -1) {    /* until end of file */
  903.     c = gchar(&pos);
  904.     if (c == initc)
  905.         count++;
  906.     else if (c == findc) {
  907.         if (count == 0)
  908.         return &pos;
  909.         count--;
  910.     }
  911.     }
  912.     return (LPTR *) NULL;    /* never found it */
  913. }
  914.  
  915. /*
  916.  * findfunc(dir) - Find the next function in direction 'dir' 
  917.  *
  918.  * Return TRUE if a function was found. 
  919.  */
  920. bool_t
  921. findfunc(dir)
  922.     int             dir;
  923. {
  924.     LPTR           *curr;
  925.  
  926.     curr = Curschar;
  927.  
  928.     do {
  929.     curr = (dir == FORWARD) ? nextline(curr) : prevline(curr);
  930.  
  931.     if (curr != NULL && curr->linep->s[0] == '{') {
  932.         setpcmark();
  933.         *Curschar = *curr;
  934.         return TRUE;
  935.     }
  936.     } while (curr != NULL);
  937.  
  938.     return FALSE;
  939. }
  940.  
  941. /*
  942.  * The following routines do the word searches performed by the 'w', 'W',
  943.  * 'b', 'B', 'e', and 'E' commands. 
  944.  */
  945.  
  946. /*
  947.  * To perform these searches, characters are placed into one of three
  948.  * classes, and transitions between classes determine word boundaries. 
  949.  *
  950.  * The classes are: 
  951.  *
  952.  * 0 - white space 1 - letters, digits, and underscore 2 - everything else 
  953.  */
  954.  
  955. static int      stype;        /* type of the word motion being performed */
  956.  
  957. #define    C0(c)    (((c) == ' ') || ((c) == '\t') || ((c) == NUL))
  958. #define    C1(c)    (isalpha(c) || isdigit(c) || ((c) == '_'))
  959.  
  960. /*
  961.  * cls(c) - returns the class of character 'c' 
  962.  *
  963.  * The 'type' of the current search modifies the classes of characters if a 'W',
  964.  * 'B', or 'E' motion is being done. In this case, chars. from class 2 are
  965.  * reported as class 1 since only white space boundaries are of interest. 
  966.  */
  967. static int
  968. cls(c)
  969.     char            c;
  970. {
  971.     if (C0(c))
  972.     return 0;
  973.  
  974.     if (C1(c))
  975.     return 1;
  976.  
  977.     /*
  978.      * If stype is non-zero, report these as class 1. 
  979.      */
  980.     return (stype == 0) ? 2 : 1;
  981. }
  982.  
  983.  
  984. /*
  985.  * fwd_word(pos, type) - move forward one word 
  986.  *
  987.  * Returns the resulting position, or NULL if EOF was reached. 
  988.  */
  989. LPTR           *
  990. fwd_word(p, type)
  991.     LPTR           *p;
  992.     int             type;
  993. {
  994.     static LPTR     pos;
  995.     int             sclass = cls(gchar(p));    /* starting class */
  996.  
  997.     pos = *p;
  998.  
  999.     stype = type;
  1000.  
  1001.     /*
  1002.      * We always move at least one character. 
  1003.      */
  1004.     if (inc(&pos) == -1)
  1005.     return NULL;
  1006.  
  1007.     if (sclass != 0) {
  1008.     while (cls(gchar(&pos)) == sclass) {
  1009.         if (inc(&pos) == -1)
  1010.         return NULL;
  1011.     }
  1012.     /*
  1013.      * If we went from 1 -> 2 or 2 -> 1, return here. 
  1014.      */
  1015.     if (cls(gchar(&pos)) != 0)
  1016.         return &pos;
  1017.     }
  1018.     /* We're in white space; go to next non-white */
  1019.  
  1020.     while (cls(gchar(&pos)) == 0) {
  1021.     /*
  1022.      * We'll stop if we land on a blank line 
  1023.      */
  1024.     if (pos.index == 0 && pos.linep->s[0] == NUL)
  1025.         break;
  1026.  
  1027.     if (inc(&pos) == -1)
  1028.         return NULL;
  1029.     }
  1030.  
  1031.     return &pos;
  1032. }
  1033.  
  1034. /*
  1035.  * bck_word(pos, type) - move backward one word 
  1036.  *
  1037.  * Returns the resulting position, or NULL if top-of-file was reached. 
  1038.  */
  1039. LPTR           *
  1040. bck_word(p, type)
  1041.     LPTR           *p;
  1042.     int             type;
  1043. {
  1044.     static LPTR     pos;
  1045.     int             sclass = cls(gchar(p));    /* starting class */
  1046.  
  1047.     pos = *p;
  1048.  
  1049.     stype = type;
  1050.  
  1051.     if (dec(&pos) == -1)
  1052.     return NULL;
  1053.  
  1054.     /*
  1055.      * If we're in the middle of a word, we just have to back up to the start
  1056.      * of it. 
  1057.      */
  1058.     if (cls(gchar(&pos)) == sclass && sclass != 0) {
  1059.     /*
  1060.      * Move backward to start of the current word 
  1061.      */
  1062.     while (cls(gchar(&pos)) == sclass) {
  1063.         if (dec(&pos) == -1)
  1064.         return NULL;
  1065.     }
  1066.     inc(&pos);        /* overshot - forward one */
  1067.     return &pos;
  1068.     }
  1069.     /*
  1070.      * We were at the start of a word. Go back to the start of the prior
  1071.      * word. 
  1072.      */
  1073.  
  1074.     while (cls(gchar(&pos)) == 0) {    /* skip any white space */
  1075.     /*
  1076.      * We'll stop if we land on a blank line 
  1077.      */
  1078.     if (pos.index == 0 && pos.linep->s[0] == NUL)
  1079.         return &pos;
  1080.  
  1081.     if (dec(&pos) == -1)
  1082.         return NULL;
  1083.     }
  1084.  
  1085.     sclass = cls(gchar(&pos));
  1086.  
  1087.     /*
  1088.      * Move backward to start of this word. 
  1089.      */
  1090.     while (cls(gchar(&pos)) == sclass) {
  1091.     if (dec(&pos) == -1)
  1092.         return NULL;
  1093.     }
  1094.     inc(&pos);            /* overshot - forward one */
  1095.  
  1096.     return &pos;
  1097. }
  1098.  
  1099. /*
  1100.  * end_word(pos, type) - move to the end of the word 
  1101.  *
  1102.  * There is an apparent bug in the 'e' motion of the real vi. At least on the
  1103.  * System V Release 3 version for the 80386. Unlike 'b' and 'w', the 'e'
  1104.  * motion crosses blank lines. When the real vi crosses a blank line in an
  1105.  * 'e' motion, the cursor is placed on the FIRST character of the next
  1106.  * non-blank line. The 'E' command, however, works correctly. Since this
  1107.  * appears to be a bug, I have not duplicated it here. 
  1108.  *
  1109.  * Returns the resulting position, or NULL if EOF was reached. 
  1110.  */
  1111. LPTR           *
  1112. end_word(p, type)
  1113.     LPTR           *p;
  1114.     int             type;
  1115. {
  1116.     static LPTR     pos;
  1117.     int             sclass = cls(gchar(p));    /* starting class */
  1118.  
  1119.     pos = *p;
  1120.  
  1121.     stype = type;
  1122.  
  1123.     if (inc(&pos) == -1)
  1124.     return NULL;
  1125.  
  1126.     /*
  1127.      * If we're in the middle of a word, we just have to move to the end of
  1128.      * it. 
  1129.      */
  1130.     if (cls(gchar(&pos)) == sclass && sclass != 0) {
  1131.     /*
  1132.      * Move forward to end of the current word 
  1133.      */
  1134.     while (cls(gchar(&pos)) == sclass) {
  1135.         if (inc(&pos) == -1)
  1136.         return NULL;
  1137.     }
  1138.     dec(&pos);        /* overshot - forward one */
  1139.     return &pos;
  1140.     }
  1141.     /*
  1142.      * We were at the end of a word. Go to the end of the next word. 
  1143.      */
  1144.  
  1145.     while (cls(gchar(&pos)) == 0) {    /* skip any white space */
  1146.     if (inc(&pos) == -1)
  1147.         return NULL;
  1148.     }
  1149.  
  1150.     sclass = cls(gchar(&pos));
  1151.  
  1152.     /*
  1153.      * Move forward to end of this word. 
  1154.      */
  1155.     while (cls(gchar(&pos)) == sclass) {
  1156.     if (inc(&pos) == -1)
  1157.         return NULL;
  1158.     }
  1159.     dec(&pos);            /* overshot - forward one */
  1160.  
  1161.     return &pos;
  1162. }
  1163. SHAR_EOF
  1164. cat << \SHAR_EOF > source.doc
  1165.  
  1166.          Release Notes for STEVIE - Version 3.10a
  1167.  
  1168.                   Source Notes
  1169.  
  1170.               Tony Andrews - March 6, 1988
  1171.  
  1172. Overview
  1173. --------
  1174.  
  1175.     This file provides a brief description of the source code for
  1176. Stevie. The data structures are described later as well. For information
  1177. specific to porting the editor, see the file 'porting.doc'. This document
  1178. is more relevant to people who want to hack on the editor apart from doing
  1179. a simple port.
  1180.  
  1181.     Most of this document was written some time ago so a lot of the
  1182. discussion centers on problems related to the Atari ST environment and
  1183. compilers. Most of this can be ignored for other systems.
  1184.  
  1185. Things You Need
  1186. ---------------
  1187.  
  1188.     Stevie has been compiled with both the Alcyon (4.14A) and the
  1189. Megamax C compilers. For the posted binary, Megamax was used because
  1190. it's less buggy and provides a reasonable malloc(). Ports to other
  1191. compilers should be pretty simple. The current ifdef's for ALCYON and
  1192. MEGAMAX should point to the potential trouble areas. (See 'porting.doc'
  1193. for more information.)
  1194.  
  1195.     The search code depends on Henry Spencer's regular expression
  1196. code. I used a version I got from the net recently (as part of a 'grep'
  1197. posting) and had absolutely no trouble compiling it on the ST. Thanks,
  1198. Henry!
  1199.  
  1200.     The file 'getenv.c' contains a getenv routine that may or may
  1201. not be needed with your compiler. My version works with Alcyon and
  1202. Megamax, under either the Beckemeyer or Gulam shells.
  1203.  
  1204.     Lastly, you need a decent malloc. Lots of stuff in stevie is
  1205. allocated dynamically. The malloc with Alcyon is problematic because
  1206. it allocates from the heap between the end of data and the top of stack.
  1207. If you make the stack big enough to edit large files, you wind up
  1208. wasting space when working with small files. Mallocs that get their memory
  1209. from GEMDOS (in fairly large chunks) are much better.
  1210.  
  1211. Data Structures
  1212. ---------------
  1213.  
  1214.     A brief discussion of the evolution of the data structures will
  1215. do much to clarify the code, and explain some of the strangeness you may
  1216. see.
  1217.  
  1218.     In the original version, the file was maintained in memory as a
  1219. simple contiguous buffer. References to positions in the file were simply
  1220. character pointers. Due to the obvious performance problems inherent in
  1221. this approach, I made the following changes.
  1222.  
  1223.     The file is now represented by a doubly linked list of 'line'
  1224. structures defined as follows:
  1225.  
  1226. struct    line {
  1227.     struct    line   *next;    /* next line */
  1228.     struct    line   *prev;    /* previous line */
  1229.     char           *s;    /* text for this line */
  1230.     int            size;    /* actual size of space at 's' */
  1231.     unsigned long   num;    /* line "number" */
  1232. };
  1233.  
  1234. The members of the line structure are described more completely here:
  1235.  
  1236. prev    - pointer to the structure for the prior line, or NULL for the
  1237.       first line of the file
  1238.  
  1239. next    - like 'prev' but points to the next line
  1240.  
  1241. s    - points to the contents of the line (null terminated)
  1242.  
  1243. size    - contains the size of the chunk of space pointed to by s. This
  1244.       is used so we know when we can add text to a line without getting
  1245.       more space. When we DO need more space, we always get a little
  1246.       extra so we don't make so many calls to malloc.
  1247.  
  1248. num    - This is a pseudo line number that makes it easy to compare
  1249.       positions within the file. Otherwise, we'd have to traverse
  1250.       all the links to tell which line came first.
  1251.  
  1252.     Since character pointers served to mark file positions in the
  1253. original, a similar data object was needed for the new data structures.
  1254. This purpose is served by the 'lptr' structure which is defined as:
  1255.  
  1256. struct    lptr {
  1257.     struct    line   *linep;    /* line we're referencing */
  1258.     int             index;    /* position within that line */
  1259. };
  1260.  
  1261. The member 'linep' points to the 'line' structure for the line containing
  1262. the location of interest. The integer 'index' is the offset into the line
  1263. data (member 's') of the character to be referenced.
  1264.  
  1265. The following typedef's are more commonly used:
  1266.  
  1267. typedef    struct line    LINE;
  1268. typedef    struct lptr    LPTR;
  1269.  
  1270. Many operations that were trivial with character pointers had to be
  1271. implemented by functions or macros to manipulate LPTR's. Most of these are in
  1272. the files 'ptrfunc.c' and 'macros.h'. There you'll find functions to increment,
  1273. decrement, and compare LPTR's.
  1274. SHAR_EOF
  1275. cat << \SHAR_EOF > stevie.doc
  1276.  
  1277.         STEVIE - Simply Try this Editor for VI Enthusiasts
  1278.  
  1279.              Quick Reference Card
  1280.  
  1281.                   by
  1282.  
  1283.               Tony Andrews And G. R. (Fred) Walter
  1284.  
  1285. STEVIE may be freely distributed. The source isn't copyrighted or
  1286. restricted in any way. If you pass the program along, please include all
  1287. the documentation and, if practical, the source as well.
  1288.  
  1289. STEVIE used to stand for 'ST Editor for VI Enthusiasts', however since this
  1290. editor is used on more machines than just ST's the acronym was changed.
  1291.  
  1292. Starting the Editor
  1293. -------------------
  1294.  
  1295. The following command line forms are supported:
  1296.  
  1297.     vi [file ...]        Edit the specified file(s)
  1298.  
  1299.     vi -t tag        Start at location of the given tag
  1300.  
  1301.     vi + file        Edit file starting at end
  1302.  
  1303.     vi +n file        Edit file starting a line number 'n'
  1304.  
  1305.     vi +/pat file        Edit file starting at pattern 'pat'
  1306.  
  1307. If multiple files are given on the command line (using the first form),
  1308. the ":n" command goes to the next file, ":p" goes backward in the list,
  1309. and ":rew" can be used to rewind back to the start of the file list.
  1310.  
  1311. Set Command Options
  1312. -------------------
  1313.  
  1314. The ":set" command works as usual to set parameters. Each parameter has
  1315. a long and an abbreviated name, either of which may be used. Boolean
  1316. parameters are set as in:
  1317.  
  1318.     set showmatch
  1319.  
  1320. or cleared by:
  1321.  
  1322.     set noshowmatch
  1323.  
  1324. Numeric parameters are set as in:
  1325.  
  1326.     set scroll=5
  1327.  
  1328. Several parameters may be set with a single command:
  1329.  
  1330.     set novb sm report=1
  1331.  
  1332. To see the status of all parameters use ":set all". Typing ":set" with
  1333. no arguments will show only those parameters that have been changed.
  1334. The supported parameters, their names, defaults, and descriptions are
  1335. shown below:
  1336.  
  1337. Full Name    Short    Default        Description
  1338. ------------------------------------------------------------------------------
  1339. vbell        vb    vb        Use visual bell (novb for audible bell)
  1340. showmatch    sm    nosm        Showmatch mode
  1341. wrapscan    ws    ws        Wrapscan (searches cross file start/end)
  1342. errorbells    eb    noeb        Ring bell when error messages are shown
  1343. showmode    mo    nomo        Show on status line when in insert mode
  1344. backup        bk    nobk        Leave backup in *.bak on file writes
  1345. return        cr    cr        End lines with cr-lf when writing
  1346. list        list    nolist        Show tabs and newlines graphically
  1347.  
  1348. scroll        scroll    12        Number of lines to scroll for ^D and ^U
  1349. tabstop        ts    8        Number of spaces in a tab
  1350. report        report    5        Min # of lines to report operations on
  1351. lines        lines    25        Number of lines on the screen
  1352.  
  1353.  
  1354. The EXINIT environment variable can be used to modify the default values
  1355. on startup as in:
  1356.  
  1357.         setenv EXINIT="set sm ts=4"
  1358.  
  1359. The 'backup' parameter, if set, causes the editor to retain a backup of any
  1360. files that are written. During file writes, a backup is always kept for
  1361. safety until the write is completed. At that point, the 'backup' parameter
  1362. determines whether the backup file is deleted.
  1363.  
  1364. In environments (e.g. OS/2 or TOS) where lines are normally terminated by
  1365. CR-LF, the 'return' parameter allows files to be written with only a LF
  1366. terminator (if the parameter is cleared).
  1367.  
  1368. The 'lines' parameter tells the editor how many lines there are on the screen.
  1369. This is useful on systems like the ST where various screen resolutions may be
  1370. used. By using the 'lines' parameter, different screen sizes can be easily
  1371. handled. On the Amiga system window resizes are atomatically detected and
  1372. acted upon. It is suggested that one's window be larger than 2 rows and 5
  1373. columns.
  1374.  
  1375.  
  1376. File Manipulation Commands
  1377. --------------------------
  1378.  
  1379. :w        write the current file
  1380. :wq        write and quit
  1381. :x        write (if necessary) and quit
  1382. ZZ        same as ":x"
  1383.  
  1384. :e file        edit the named file
  1385. :e!        re-edit the current file, discarding any changes
  1386. :e #        edit the alternate file
  1387.  
  1388. :w file        write the buffer to the named file
  1389. :x,y w file    write lines x through y to the named file
  1390. :r file        read the named file into the buffer
  1391.  
  1392. :n        edit the next file
  1393. :p        edit the previous file
  1394. :rew        rewind the file list
  1395.  
  1396. :f        show the current file name
  1397. :f name        change the current file name
  1398.  
  1399. :ta tag        go to the named tag
  1400. ^]        like ":ta" using the current word as the tag
  1401.  
  1402. :help        display a command summary
  1403.  
  1404. The ":help" command can also be invoke with the <HELP> key on the Atari ST
  1405. or the Amiga. This actually displays a pretty complete summary of the real vi
  1406. with unsupported features indicated appropriately.
  1407.  
  1408. The commands above work pretty much like they do in 'vi'. Most of the
  1409. commands support a '!' suffix (if appropriate) to discard any pending
  1410. changes.
  1411.  
  1412. When writing just part of the buffer, the following address forms are
  1413. supported:
  1414.  
  1415.         addr [+- number]
  1416.  
  1417. where 'addr' may be one of the following:
  1418.  
  1419.         a line number
  1420.         a mark (as in 'a or 'b)
  1421.         '.' (the current line)
  1422.         '$' (the last line)
  1423.  
  1424.  
  1425. String Searches
  1426. ---------------
  1427.  
  1428. String searches are supported, as in vi, accepting the usual regular
  1429. expression syntax. This was done using Henry Spencer's regular expression
  1430. library without modification. Tony Andrews added code outside the library to
  1431. support the '\<' and '\>' extensions.
  1432.  
  1433. Operators
  1434. ---------
  1435.  
  1436. The vi operators (d, c, y, <, and >) work as true operators.
  1437.  
  1438. Tags
  1439. ----
  1440.  
  1441. Tags are implemented.
  1442.  
  1443. System-Specific Comments
  1444. ------------------------
  1445.  
  1446. The following sections provide additional relevant information for the
  1447. systems to which STEVIE has been ported.
  1448.  
  1449. Atari ST
  1450. --------
  1451.  
  1452. The editor has been tested in all three resolutions, although low and
  1453. high res. are less tested than medium. The 50-line high res. mode can
  1454. be used by setting the 'lines' parameter to 50. Alternatively, the
  1455. environment variable 'LINES' can be set. The editor doesn't actively
  1456. set the number of lines on the screen. It just operates using the number
  1457. of lines it was told.
  1458.  
  1459. The arrow keys, as well as the <INSERT>, <HELP>, and <UNDO> keys are
  1460. all mapped appropriately.
  1461.  
  1462. UNIX
  1463. ----
  1464.  
  1465. The editor has been ported to UNIX System V release 3. This was done
  1466. mainly to get some profiling data so I haven't put much effort into
  1467. doing the UNIX version right. It's hard-coded for ansi-style escape
  1468. sequences and doesn't use the termcap/terminfo routines at all.
  1469.  
  1470. OS/2
  1471. ----
  1472.  
  1473. This port was done because the editor that comes with the OS/2 developer's
  1474. kit really sucks. Make sure 'ansi' mode is on (using the 'ansi' command).
  1475. The OS/2 ansi driver doesn't support insert/delete line, so the display
  1476. updates are a little rough, but the editor is fast enough that it isn't
  1477. too bothersome. The arrow keys are NOT mapped, so they don't currently do
  1478. anything reasonable.
  1479.  
  1480. BSD 4.3
  1481. -------
  1482.  
  1483. This port was done so it could be worked on in a main-frame enviroment.
  1484.  
  1485. Amiga
  1486. -----
  1487.  
  1488. The arrow keys and the help key are supported, as is window re-sizing.
  1489. It is strongly suggested that you not try to type in console commands
  1490. (alt-esc in some keymaps, plus the appropriate other keys) since STEVIE
  1491. captures all console input. If you do type alt-esc then typing '|' will
  1492. return you to STEVIE.
  1493.  
  1494. Missing Features
  1495. ----------------
  1496.  
  1497. 1. Macros with support for function keys.
  1498.  
  1499. 2. More "set" options.
  1500.  
  1501. 3. Auto-indent.
  1502.  
  1503. 4. Many others...
  1504.  
  1505. Known Bugs and Problems
  1506. -----------------------
  1507.  
  1508. 1. The yank buffer uses statically allocated memory, so yanks of more than
  1509.    5K of text will fail. If a delete spans more than 5K, the program asks
  1510.    for confirmation before proceeding. That way, if you were moving text,
  1511.    you don't get screwed by the limited yank buffer. You just have to move
  1512.    smaller chunks at a time. All the internal buffers (yank, redo, etc.)
  1513.    need to be reworked to allocate memory dynamically.
  1514.  
  1515. 2. If you stay in insert mode for a long time (around 5K's worth of
  1516.    characters, including newlines) the insert buffer can overflow.
  1517.    When this happens you lose your ability to automatically undo the text just
  1518.    inserted and the redo/undo/(undo of undo) buffers are reset to the
  1519.    current position.
  1520.  
  1521. 3. Several other less bothersome glitches...
  1522.  
  1523. Character Function Summary
  1524. --------------------------
  1525.  
  1526. The following list describes the meaning of each character that's used
  1527. by the editor. In some cases characters have meaning in both command and
  1528. insert mode; these are all described.
  1529.  
  1530. ^@    The null character. Not used in any mode. This character may not
  1531.     be present in the file, as is the case with vi.
  1532.  
  1533. ^B    Backward one screen.
  1534.  
  1535. ^D    Scroll the window down one half screen.
  1536.  
  1537. ^E    Scroll the screen up one line.
  1538.  
  1539. ^F    Forward one screen.
  1540.  
  1541. ^G    Same as ":f" command. Displays file information.
  1542.  
  1543. ^H (BS)    Moves cursor left one space in command mode. In insert mode, erases
  1544.     the last character typed.
  1545.  
  1546. ^J    Move the cursor down one line.
  1547.  
  1548. ^L    Clear and redraw the screen.
  1549.  
  1550. ^M (CR)    Move to the first non-white character in the next line. In insert
  1551.     mode, a carriage return opens a new line for input.
  1552.  
  1553. ^N    Move the cursor down a line.
  1554.  
  1555. ^P    Move the cursor up a line.
  1556.  
  1557. ^U    Scroll the window up one half screen.
  1558.  
  1559. ^V    Indicates that the next character is should be treated as entered
  1560.     and not modified (used to enter control characters, etc.).
  1561.  
  1562. ^Y    Scroll the screen down one line.
  1563.  
  1564. ^[    Escape cancels a pending command in command mode, and is used to
  1565.     terminate insert mode.
  1566.  
  1567. ^]    Moves to the tag whose name is given by the word in which the cursor
  1568.     resides.
  1569.  
  1570. ^`    Same as ":e #" if supported (system-dependent).
  1571.  
  1572. SPACE    Move the cursor right on column.
  1573.  
  1574. $    Move to the end of the current line.
  1575.  
  1576. %    If the cursor rests on a paren '()', brace '{}', or bracket '[]',
  1577.     move to the matching one.
  1578.  
  1579. '    Used to move the cursor to a previously marked position, as in
  1580.     'a or 'b. The cursor moves to the start of the marked line. The
  1581.     special mark '' refers to the "previous context".
  1582.  
  1583. +    Same as carriage return, in command mode.
  1584.  
  1585. ,    Reverse of the last t, T, f, or F command.
  1586.  
  1587. -    Move to the first non-white character in the previous line.
  1588.  
  1589. .    Repeat the last edit command.
  1590.  
  1591. /    Start of a forward string search command. String searches may be
  1592.     optionally terminated with a closing slash. To search for a slash
  1593.     use '\/' in the search string.
  1594.  
  1595. 0    Move to the start of the current line. Also used within counts.
  1596.  
  1597. 1-9    Used to add 'count' prefixes to commands.
  1598.  
  1599. :    Prefix character for "ex" commands.
  1600.  
  1601. ;    Repeat last t, T, f, or F command.
  1602.  
  1603. <    The 'left shift' operator.
  1604.  
  1605. >    The 'right shift' operator.
  1606.  
  1607. ?    Same as '/', but search backward.
  1608.  
  1609. A    Append at the end of the current line.
  1610.  
  1611. B    Backward one blank-delimited word.
  1612.  
  1613. C    Change the rest of the current line.
  1614.  
  1615. D    Delete the rest of the current line.
  1616.  
  1617. E    End of the end of a blank-delimited word.
  1618.  
  1619. F    Find a character backward on the current line.
  1620.  
  1621. G    Go to the given line number (end of file, by default).
  1622.  
  1623. H    Move to the first non-white char. on the top screen line.
  1624.  
  1625. I    Insert before the first non-white char. on the current line.
  1626.  
  1627. J    Join two lines.
  1628.  
  1629. L    Move to the first non-white char. on the bottom screen line.
  1630.  
  1631. M    Move to the first non-white char. on the middle screen line.
  1632.  
  1633. N    Reverse the last string search.
  1634.  
  1635. O    Open a new line above the current line, and start inserting.
  1636.  
  1637. P    Put the yank/delete buffer before the current cursor position.
  1638.  
  1639. T    Reverse search 'upto' the given character.
  1640.  
  1641. W    Move forward one blank-delimited word.
  1642.  
  1643. X    Delete one character before the cursor.
  1644.  
  1645. Y    Yank the current line. Same as 'yy'.
  1646.  
  1647. ZZ    Exit from the editor, saving changes if necessary.
  1648.  
  1649. [[    Move backward one C function.
  1650.  
  1651. ]]    Move forward one C function.
  1652.  
  1653. ^    Move to the first non-white on the current line.
  1654.  
  1655. `    Move to the given mark, as with '. The distinction between the two
  1656.     commands is important when used with operators. I support the
  1657.     difference correctly. If you don't know what I'm talking about,
  1658.     don't worry, it won't matter to you.
  1659.  
  1660. ~       Switch case of character under cursor.
  1661.  
  1662. a    Append text after the cursor.
  1663.  
  1664. b    Back one word.
  1665.  
  1666. c    The change operator.
  1667.  
  1668. d    The delete operator.
  1669.  
  1670. e    Move to the end of a word.
  1671.  
  1672. f    Find a character on the current line.
  1673.  
  1674. h    Move left one column.
  1675.  
  1676. i    Insert text before the cursor.
  1677.  
  1678. j    Move down one line.
  1679.  
  1680. k    Move up one line.
  1681.  
  1682. l    Move right one column.
  1683.  
  1684. m    Set a mark at the current position (e.g. ma or mb).
  1685.  
  1686. n    Repeat the last string search.
  1687.  
  1688. o    Open a new line and start inserting text.
  1689.  
  1690. p    Put the yank/delete buffer after the cursor.
  1691.  
  1692. r    Replace a character.
  1693.  
  1694. s    Replace characters.
  1695.  
  1696. t    Move forward 'upto' the given character on the current line.
  1697.  
  1698. u    Undo the last edit.
  1699.  
  1700. w    Move forward one word.
  1701.  
  1702. x    Delete the character under the cursor.
  1703.  
  1704. y    The yank operator.
  1705.  
  1706. z    Redraw the screen with the current line at the top (zRETURN),
  1707.     the middle (z.), or the bottom (z-).
  1708.  
  1709. |    Move to the column given by the preceding count.
  1710. SHAR_EOF
  1711. cat << \SHAR_EOF > stevie.h
  1712. /*
  1713.  * STEVIE - Simply Try this Editor for VI Enthusiasts
  1714.  *
  1715.  * Code Contributions By : Tim Thompson           twitch!tjt
  1716.  *                         Tony Andrews           onecom!wldrdg!tony 
  1717.  *                         G. R. (Fred) Walter    watmath!watcgl!grwalter 
  1718.  */
  1719.  
  1720. /*
  1721.  * One (and only 1) of the following defines should be uncommented. Most of
  1722.  * the code is pretty machine-independent. Machine dependent code goes in a
  1723.  * file like tos.c or unix.c. The only other place where machine dependent
  1724.  * code goes is term.h for escape sequences. 
  1725.  */
  1726.  
  1727. #ifndef AMIGA
  1728. /* #define    ATARI        Atari ST */
  1729. /* #define    UNIX        System V */
  1730. #define    BSD            BSD 4.3 */
  1731. /* #define    OS2        Microsoft OS/2 */
  1732. /* #define    AMIGA        Amiga */
  1733. #endif
  1734.  
  1735. /*
  1736.  * If ATARI is defined, one of the following compilers must be selected. 
  1737.  */
  1738. #ifdef    ATARI
  1739. #define    MEGAMAX            Megamax Compiler */
  1740. /* #define    ALCYON        Alcyon C compiler */
  1741. #endif
  1742.  
  1743. /*
  1744.  * If HELP is defined, the :help command shows a vi command summary. 
  1745.  */
  1746. #define    HELP            /* enable help command */
  1747.  
  1748. #include <stdio.h>
  1749. #ifndef ATARI
  1750. # ifndef UNIX
  1751. #  ifndef OS2
  1752. #   include <stdlib.h>
  1753. #  endif
  1754. # endif
  1755. #endif
  1756. #include <ctype.h>
  1757. #include <string.h>
  1758. #include "ascii.h"
  1759. #include "keymap.h"
  1760. #include "param.h"
  1761. #include "term.h"
  1762. #include "macros.h"
  1763.  
  1764. #ifdef AMIGA
  1765. /*
  1766.  * This won't be needed if you have a version of Lattice 4.01 without broken
  1767.  * break signal handling.
  1768.  */
  1769. #include <signal.h>
  1770. #endif
  1771.  
  1772. extern char    *strchr();
  1773.  
  1774. #define NORMAL   0
  1775. #define CMDLINE  1
  1776. #define INSERT   2
  1777. #define APPEND   3
  1778. #define FORWARD  4
  1779. #define BACKWARD 5
  1780.  
  1781. /*
  1782.  * Boolean type definition and constants 
  1783.  */
  1784. typedef int     bool_t;
  1785.  
  1786. #ifndef    TRUE
  1787. #define    FALSE    (0)
  1788. #define    TRUE    (1)
  1789. #endif
  1790. #define    SORTOF    (2)
  1791. #define YES      TRUE
  1792. #define NO       FALSE
  1793. #define MAYBE    SORTOF
  1794.  
  1795. /*
  1796.  * Maximum screen dimensions
  1797.  */
  1798. #define MAX_COLUMNS 140L
  1799.  
  1800. /*
  1801.  * Buffer sizes
  1802.  */
  1803. #define CMDBUFFSIZE MAX_COLUMNS    /* size of the command processing buffer */
  1804.  
  1805. #define LSIZE        512    /* max. size of a line in the tags file */
  1806.  
  1807. #define IOSIZE     (1024+1)    /* file i/o and sprintf buffer size */
  1808.  
  1809. #define YANKSIZE    5200    /* yank buffer size */
  1810. #define INSERT_SIZE 5300    /* insert, redo and undo buffer size must be
  1811.                  * bigger than YANKSIZE */
  1812. #define REDO_UNDO_SIZE 5400    /* redo, undo and (undo an undo) buffer size
  1813.                  * must be bigger than INSERT_SIZE */
  1814. #define READSIZE    5500    /* read buffer size must be bigger than
  1815.                  * YANKSIZE and REDO_UNDO_SIZE */
  1816.  
  1817. /*
  1818.  * SLOP is the amount of extra space we get for text on a line during editing
  1819.  * operations that need more space. This keeps us from calling malloc every
  1820.  * time we get a character during insert mode. No extra space is allocated
  1821.  * when the file is initially read. 
  1822.  */
  1823. #define    SLOP    10
  1824.  
  1825. /*
  1826.  * LINEINC is the gap we leave between the artificial line numbers. This
  1827.  * helps to avoid renumbering all the lines every time a new line is
  1828.  * inserted. 
  1829.  */
  1830. #define    LINEINC    10
  1831.  
  1832. #define CHANGED   { Changed = TRUE; }
  1833. #define UNCHANGED { Changed = FALSE; }
  1834.  
  1835. struct line {
  1836.     struct line    *next;    /* next line */
  1837.     struct line    *prev;    /* previous line */
  1838.     char           *s;        /* text for this line */
  1839.     int             size;    /* actual size of space at 's' */
  1840.     unsigned long   num;    /* line "number" */
  1841. };
  1842.  
  1843. #define    LINEOF(x)    ((x)->linep->num)
  1844.  
  1845. struct lptr {
  1846.     struct line    *linep;    /* line we're referencing */
  1847.     int             index;    /* position within that line */
  1848. };
  1849.  
  1850. typedef struct line LINE;
  1851. typedef struct lptr LPTR;
  1852.  
  1853. struct charinfo {
  1854.     char            ch_size;
  1855.     char           *ch_str;
  1856. };
  1857.  
  1858. extern struct charinfo chars[];
  1859.  
  1860. extern int      State;
  1861. extern int      Rows;
  1862. extern int      Columns;
  1863. extern char    *Realscreen;
  1864. extern char    *Nextscreen;
  1865. extern char    *Filename;
  1866. extern LPTR    *Filemem;
  1867. extern LPTR    *Fileend;
  1868. extern LPTR    *Topchar;
  1869. extern LPTR    *Botchar;
  1870. extern LPTR    *Curschar;
  1871. extern LPTR    *Insstart;
  1872. extern int      Cursrow, Curscol, Cursvcol, Curswant;
  1873. extern bool_t   set_want_col;
  1874. extern int      Prenum;
  1875. extern bool_t   Changed;
  1876. extern bool_t   RedrawingDisabled;
  1877. extern bool_t   MustRedrawLine;
  1878. extern bool_t   MustRedrawScreen;
  1879. extern bool_t   UndoInProgress;
  1880. extern bool_t   Binary;
  1881. extern char    *IObuff;
  1882. extern char    *Insbuffptr;
  1883. extern char    *Insbuff;
  1884. extern char    *Readbuffptr;
  1885. extern char    *Readbuff;
  1886. extern char    *Redobuffptr;
  1887. extern char    *Redobuff;
  1888. extern char    *Undobuffptr;
  1889. extern char    *Undobuff;
  1890. extern char    *UndoUndobuffptr;
  1891. extern char    *UndoUndobuff;
  1892. extern char    *Yankbuffptr;
  1893. extern char    *Yankbuff;
  1894. extern char     last_command;
  1895. extern char     last_command_char;
  1896.  
  1897. extern char *malloc(), *strcpy();
  1898.  
  1899. /* alloc.c */
  1900. char  *alloc();
  1901. char  *strsave();
  1902. void   screenalloc(), filealloc(), freeall();
  1903. LINE  *newline();
  1904. bool_t canincrease();
  1905.  
  1906. /* cmdline.c */
  1907. void   readcmdline();
  1908. void   dotag();
  1909. void   msg(), emsg(), smsg();
  1910. void   gotocmdline();
  1911. void   wait_return();
  1912.  
  1913. /* dec.c */
  1914. int    dec();
  1915.  
  1916. /* edit.c */
  1917. void   edit(), insertchar(), getout(), scrollup(), scrolldown(), beginline();
  1918. bool_t oneright(), oneleft(), oneup(), onedown();
  1919.  
  1920. /* fileio.c */
  1921. void   filemess(), renum();
  1922. bool_t readfile(), writeit();
  1923.  
  1924. /* updateNextscreen.c */
  1925. void   updateNextscreen();
  1926.  
  1927. /* help.c */
  1928. bool_t help();
  1929.  
  1930. /* inc.c */
  1931. int    inc();
  1932.  
  1933. /* linefunc.c */
  1934. LPTR   *nextline(), *prevline(), *coladvance();
  1935.  
  1936. /* main.c */
  1937. void   stuffReadbuff();
  1938. void   stuffnumReadbuff();
  1939. char   vgetc();
  1940. char   vpeekc();
  1941.  
  1942. /* mark.c */
  1943. void   setpcmark(), clrall(), clrmark();
  1944. bool_t setmark();
  1945. LPTR  *getmark();
  1946.  
  1947. /* misccmds.c */
  1948. bool_t opencmd();
  1949. void   fileinfo(), inschar(), insstr(), delline();
  1950. bool_t delchar();
  1951. int    cntllines(), plines();
  1952. LPTR  *gotoline();
  1953.  
  1954. /* updateRealscreen.c */
  1955. void   updateRealscreen();
  1956.  
  1957. /* normal.c */
  1958. void   normal();
  1959. void   ResetBuffers();
  1960. void   AppendToRedobuff();
  1961. void   AppendNumberToRedobuff();
  1962. void   AppendToUndobuff();
  1963. void   AppendNumberToUndobuff();
  1964. void   AppendPositionToUndobuff();
  1965. void   AppendToUndoUndobuff();
  1966. void   AppendNumberToUndoUndobuff();
  1967. void   AppendPositionToUndoUndobuff();
  1968. char  *mkstr();
  1969.  
  1970. /* param.c */
  1971. void   doset();
  1972.  
  1973. /* screen.c */
  1974. void   nexttoscreen();
  1975. void   updateline();
  1976. void   redrawline();
  1977. void   screenclear();
  1978. void   cursupdate();
  1979. void   s_ins(), s_del();
  1980.  
  1981. /* search.c */
  1982. void   dosearch();
  1983. void   searchagain();
  1984. void   repsearch();
  1985. bool_t searchc(), crepsearch(), findfunc();
  1986. LPTR  *showmatch();
  1987. LPTR  *fwd_word(), *bck_word(), *end_word();
  1988.  
  1989. /*
  1990.  * Machine-dependent routines. 
  1991.  */
  1992. #ifdef AMIGA
  1993. # include "amiga.h"
  1994. #endif
  1995. #ifdef BSD
  1996. # include "bsd.h"
  1997. #endif
  1998. #ifdef UNIX
  1999. # include "unix.h"
  2000. #endif
  2001. #ifdef TOS
  2002. # include "tos.h"
  2003. #endif
  2004. #ifdef OS2
  2005. # include "os2.h"
  2006. #endif
  2007. SHAR_EOF
  2008. cat << \SHAR_EOF > term.h
  2009. /*
  2010.  * STEVIE - Simply Try this Editor for VI Enthusiasts
  2011.  *
  2012.  * Code Contributions By : Tim Thompson           twitch!tjt
  2013.  *                         Tony Andrews           onecom!wldrdg!tony 
  2014.  *                         G. R. (Fred) Walter    watmath!watcgl!grwalter 
  2015.  */
  2016.  
  2017. /*
  2018.  * This file contains the machine dependent escape sequences that the editor
  2019.  * needs to perform various operations. Some of the sequences here are
  2020.  * optional. Anything not available should be indicated by a null string. In
  2021.  * the case of insert/delete line sequences, the editor checks the capability
  2022.  * and works around the deficiency, if necessary. 
  2023.  *
  2024.  * Currently, insert/delete line sequences are used for screen scrolling. There
  2025.  * are lots of terminals that have 'index' and 'reverse index' capabilities,
  2026.  * but no line insert/delete. For this reason, the editor routines s_ins()
  2027.  * and s_del() should be modified to use 'index' sequences when the line to
  2028.  * be inserted or deleted at line zero. 
  2029.  */
  2030.  
  2031. /*
  2032.  * The macro names here correspond (more or less) to the actual ANSI names 
  2033.  */
  2034.  
  2035. #ifdef    ATARI
  2036. #define    T_EL    "\033l"        /* erase the entire current line */
  2037. #define    T_IL    "\033L"        /* insert one line */
  2038. #define    T_IL_B    ""
  2039. #define    T_DL    "\033M"        /* delete one line */
  2040. #define    T_DL_B    ""
  2041. #define    T_SC    "\033j"        /* save the cursor position */
  2042. #define    T_ED    "\033E"        /* erase display (may optionally home cursor) */
  2043. #define    T_RC    "\033k"        /* restore the cursor position */
  2044. #define    T_CI    "\033f"        /* invisible cursor (very optional) */
  2045. #define    T_CV    "\033e"        /* visible cursor (very optional) */
  2046. #define T_TP    ""        /* plain text */
  2047. #define T_TI    ""        /* inverse-video text */
  2048. #endif
  2049.  
  2050. #ifdef    UNIX
  2051. /*
  2052.  * The UNIX sequences are hard-wired for ansi-like terminals. I should really
  2053.  * use termcap/terminfo, but the UNIX port was done for profiling, not for
  2054.  * actual use, so it wasn't worth the effort. 
  2055.  */
  2056. #define    T_EL    "\033[2K"    /* erase the entire current line */
  2057. #define    T_IL    "\033[L"    /* insert one line */
  2058. #define    T_IL_B    ""
  2059. #define    T_DL    "\033[M"    /* delete one line */
  2060. #define    T_DL_B    ""
  2061. #define    T_ED    "\033[2J"    /* erase display (may optionally home cursor) */
  2062. #define    T_SC    "\0337"        /* save the cursor position */
  2063. #define    T_RC    "\0338"        /* restore the cursor position */
  2064. #define    T_CI    ""        /* invisible cursor (very optional) */
  2065. #define    T_CV    ""        /* visible cursor (very optional) */
  2066. #define T_TP    ""        /* plain text */
  2067. #define T_TI    ""        /* inverse-video text */
  2068. #endif
  2069.  
  2070. #ifdef    BSD
  2071. /* The BSD 4.3 sequences are hard-wired for ansi-like terminals. */
  2072. #define    T_EL    "\033[2K"    /* erase the entire current line */
  2073. #define    T_IL    "\033[L"    /* insert line */
  2074. #define    T_IL_B    ""
  2075. #define    T_DL    "\033[M"    /* delete line */
  2076. #define    T_DL_B    ""
  2077. #define    T_ED    "\033[2J"    /* erase display (may optionally home cursor) */
  2078. #define    T_SC    ""        /* save the cursor position */
  2079. #define    T_RC    ""        /* restore the cursor position */
  2080. #define    T_CI    ""        /* invisible cursor (very optional) */
  2081. #define    T_CV    ""        /* visible cursor (very optional) */
  2082. #define T_TP    ""        /* plain text */
  2083. #define T_TI    ""        /* inverse-video text */
  2084. #endif
  2085.  
  2086. #ifdef    OS2
  2087. /*
  2088.  * The OS/2 ansi console driver is pretty deficient. No insert or delete line
  2089.  * sequences. The erase line sequence only erases from the cursor to the end
  2090.  * of the line. For our purposes that works out okay, since the only time
  2091.  * T_EL is used is when the cursor is in column 0. 
  2092.  */
  2093. #define    T_EL    "\033[K"    /* erase the entire current line */
  2094. #define    T_IL    ""        /* insert one line */
  2095. #define    T_IL_B    ""
  2096. #define    T_DL    ""        /* delete one line */
  2097. #define    T_DL_B    ""
  2098. #define    T_ED    "\033[2J"    /* erase display (may optionally home cursor) */
  2099. #define    T_SC    "\033[s"    /* save the cursor position */
  2100. #define    T_RC    "\033[u"    /* restore the cursor position */
  2101. #define    T_CI    ""        /* invisible cursor (very optional) */
  2102. #define    T_CV    ""        /* visible cursor (very optional) */
  2103. #define T_TP    ""        /* plain text */
  2104. #define T_TI    ""        /* inverse-video text */
  2105. #endif
  2106.  
  2107. #ifdef AMIGA
  2108. /*
  2109.  * The erase line sequence only erases from the cursor to the end of the
  2110.  * line. For our purposes that works out okay, since the only time T_EL is
  2111.  * used is when the cursor is in column 0. 
  2112.  */
  2113. #define    T_EL    "\033[K"    /* erase the entire current line */
  2114. #define    T_IL    "\033["        /* insert line */
  2115. #define    T_IL_B    "L"
  2116. #define    T_DL    "\033["        /* delete line */
  2117. #define    T_DL_B    "M"
  2118. #define    T_ED    "\014"        /* erase display (may optionally home cursor) */
  2119. #define    T_RC    ""        /* restore the cursor position */
  2120. #define    T_SC    ""        /* save the cursor position */
  2121. #define    T_CI    "\033[0 p"    /* invisible cursor (very optional) */
  2122. #define    T_CV    "\033[1 p"    /* visible cursor (very optional) */
  2123. #define T_TP    "\033[0m"    /* plain text */
  2124. #define T_TI    "\033[7m"    /* inverse-video text */
  2125. #endif
  2126. SHAR_EOF
  2127. cat << \SHAR_EOF > updateNextscreen.c
  2128. /*
  2129.  * STEVIE - Simply Try this Editor for VI Enthusiasts
  2130.  *
  2131.  * Code Contributions By : Tim Thompson           twitch!tjt
  2132.  *                         Tony Andrews           onecom!wldrdg!tony 
  2133.  *                         G. R. (Fred) Walter    watmath!watcgl!grwalter 
  2134.  */
  2135.  
  2136. #include "stevie.h"
  2137.  
  2138. /*
  2139.  * updateNextscreen() 
  2140.  *
  2141.  * Based on the current value of Topchar, transfer a screenfull of stuff from
  2142.  * Filemem to Nextscreen, and update Botchar. 
  2143.  */
  2144.  
  2145. void
  2146. updateNextscreen()
  2147. {
  2148.     int             row, col;
  2149.     register char  *screenp = Nextscreen;
  2150.     LPTR            memp;
  2151.     LPTR            save;    /* save pos. in case line won't fit */
  2152.     register char  *endscreen;
  2153.     char           *nextrow;
  2154.     char            extra[16];
  2155.     int             nextra = 0;
  2156.     char            c;
  2157.     int             n;
  2158.     int             done;
  2159.     int             srow;    /* starting row of the current line */
  2160.  
  2161.     MustRedrawLine = FALSE;
  2162.     MustRedrawScreen = TRUE;
  2163.  
  2164.     save = memp = *Topchar;
  2165.  
  2166.     /* The number of rows shown is Rows-1. */
  2167.     /* The last line is the status/command line. */
  2168.     endscreen = &screenp[(Rows - 1) * Columns];
  2169.  
  2170.     srow = done = row = col = 0;
  2171.     while (screenp < endscreen && !done) {
  2172.  
  2173.     /* Get the next character to put on the screen. */
  2174.  
  2175.     /*
  2176.      * The 'extra' array contains the extra stuff that is inserted to
  2177.      * represent special characters (tabs, and other non-printable stuff.
  2178.      * The order in the 'extra' array is reversed. 
  2179.      */
  2180.  
  2181.     if (nextra > 0)
  2182.         c = extra[--nextra];
  2183.     else {
  2184.         c = gchar(&memp);
  2185.         if (inc(&memp) == -1)
  2186.         done = 1;
  2187.         /*
  2188.          * when getting a character from the file, we may have to turn it
  2189.          * into something else on the way to putting it into
  2190.          * 'Nextscreen'. 
  2191.          */
  2192.         if (c == TAB && !P(P_LS)) {
  2193.         strcpy(extra, "        ");
  2194.         /* tab amount depends on current column */
  2195.         nextra = ((P(P_TS) - 1) - col % P(P_TS));
  2196.         c = ' ';
  2197.         } else if (c == NUL && P(P_LS)) {
  2198.         extra[0] = NUL;
  2199.         nextra = 1;
  2200.         c = '$';
  2201.         } else if ((n = chars[c].ch_size) > 1) {
  2202.         char           *p;
  2203.         nextra = 0;
  2204.         p = chars[c].ch_str;
  2205.         /* copy 'ch-str'ing into 'extra' in reverse */
  2206.         while (n > 1)
  2207.             extra[nextra++] = p[--n];
  2208.         c = p[0];
  2209.         }
  2210.     }
  2211.  
  2212.     if (c == NUL) {
  2213.         srow = ++row;
  2214.         /*
  2215.          * Save this position in case the next line won't fit on the
  2216.          * screen completely. 
  2217.          */
  2218.         save = memp;
  2219.         /* get pointer to start of next row */
  2220.         nextrow = &Nextscreen[row * Columns];
  2221.         /* blank out the rest of this row */
  2222.         while (screenp != nextrow)
  2223.         *screenp++ = ' ';
  2224.         col = 0;
  2225.         continue;
  2226.     }
  2227.     if (col >= Columns) {
  2228.         row++;
  2229.         col = 0;
  2230.     }
  2231.     /* store the character in Nextscreen */
  2232.     *screenp++ = c;
  2233.     col++;
  2234.     }
  2235.     /*
  2236.      * If we didn't hit the end of the file, and we didn't finish the last
  2237.      * line we were working on, then the line didn't fit. 
  2238.      */
  2239.     if (!done && c != NUL) {
  2240.     /*
  2241.      * Clear the rest of the screen and mark the unused lines. 
  2242.      */
  2243.     screenp = &Nextscreen[srow * Columns];
  2244.     while (screenp < endscreen)
  2245.         *screenp++ = ' ';
  2246.     for (; srow < (Rows - 1); srow++)
  2247.         Nextscreen[srow * Columns] = '@';
  2248.     *Botchar = save;
  2249.     return;
  2250.     }
  2251.     /* make sure the rest of the screen is blank */
  2252.     while (screenp < endscreen)
  2253.     *screenp++ = ' ';
  2254.     /* put '~'s on rows that aren't part of the file. */
  2255.     if (col != 0)
  2256.     row++;
  2257.     while (row < Rows) {
  2258.     Nextscreen[row * Columns] = '~';
  2259.     row++;
  2260.     }
  2261.     if (done)            /* we hit the end of the file */
  2262.     *Botchar = *Fileend;
  2263.     else
  2264.     *Botchar = memp;
  2265. }
  2266. SHAR_EOF
  2267. cat << \SHAR_EOF > updateRealscreen.c
  2268. /*
  2269.  * STEVIE - Simply Try this Editor for VI Enthusiasts
  2270.  *
  2271.  * Code Contributions By : Tim Thompson           twitch!tjt
  2272.  *                         Tony Andrews           onecom!wldrdg!tony 
  2273.  *                         G. R. (Fred) Walter    watmath!watcgl!grwalter 
  2274.  */
  2275.  
  2276. #include "stevie.h"
  2277.  
  2278. /*
  2279.  * updateRealscreen 
  2280.  *
  2281.  * Transfer the contents of Nextscreen to the screen, using Realscreen to avoid
  2282.  * unnecessary output. 
  2283.  */
  2284. void
  2285. updateRealscreen()
  2286. {
  2287.     register char  *np = Nextscreen;
  2288.     register char  *rp = Realscreen;
  2289.     register char  *endscreen;
  2290.     int             row = 0, col = 0;
  2291.     int             gorow = -1, gocol = -1;
  2292.  
  2293.     if (RedrawingDisabled)
  2294.     return;
  2295.  
  2296.     if (!MustRedrawScreen && !MustRedrawLine)
  2297.     return;
  2298.  
  2299.     if (MustRedrawLine) {
  2300.     msg("STEVIE internal error: updateRealscreen called");
  2301.     sleep(5);
  2302.     }
  2303.     endscreen = &np[(Rows - 1) * Columns];
  2304.  
  2305.     outstr(T_CI);        /* disable cursor */
  2306.  
  2307.     for (; np < endscreen; np++, rp++) {
  2308.     /* If desired screen (contents of Nextscreen) does not */
  2309.     /* match what's really there, put it there. */
  2310.     if (*np != *rp) {
  2311.         /* if we are positioned at the right place, */
  2312.         /* we don't have to use windgoto(). */
  2313.         if (gocol != col || gorow != row) {
  2314.         /*
  2315.          * If we're just off by one, don't send an entire esc. seq.
  2316.          * (this happens a lot!) 
  2317.          */
  2318.         if (gorow == row && gocol + 1 == col) {
  2319.             outchar(*(np - 1));
  2320.             gocol++;
  2321.         } else
  2322.             windgoto(gorow = row, gocol = col);
  2323.         }
  2324.         outchar(*rp = *np);
  2325.         gocol++;
  2326.     }
  2327.     if (++col >= Columns) {
  2328.         col = 0;
  2329.         row++;
  2330.     }
  2331.     }
  2332.     outstr(T_CV);        /* enable cursor again */
  2333.  
  2334.     MustRedrawLine = FALSE;
  2335.     MustRedrawScreen = FALSE;
  2336. }
  2337. SHAR_EOF
  2338. #    End of shell archive
  2339. exit 0
  2340. -- 
  2341. Bob Page, U of Lowell CS Dept.  page@swan.ulowell.edu  ulowell!page
  2342. Have five nice days.
  2343.